library IEEE; 
use IEEE.std_logic_1164.all; 
use IEEE.std_logic_arith.all; 
  
entity multiplier is
  generic (DWIDTH : integer := 8);

  port (
  	clk	: in  std_logic;
  	a_i	: in  std_logic_vector(DWIDTH-1 downto 0);  -- Multiplicand
   b_i	: in  std_logic_vector(DWIDTH-1 downto 0);  -- Multiplicator
   prod_o 	: out std_logic_vector((DWIDTH*2)-1 downto 0) -- Product
  );
end multiplier;

architecture rtl of multiplier is

			component csadder is
				 Port (   A : in  STD_LOGIC_VECTOR (15 downto 0);
						    B : in  STD_LOGIC_VECTOR (15 downto 0);
						    S : out STD_LOGIC_VECTOR (15 downto 0);
						    cin : in  STD_LOGIC;
						    carry4 : out  STD_LOGIC;
						    carry7 : out  STD_LOGIC;
							 carry8 : out  STD_LOGIC;
							 carry15 : out  STD_LOGIC;
						    carry16 : out  STD_LOGIC);
			end component;
			
			signal B_i_16Bits			: std_logic_vector((DWIDTH*2)-1 downto 0);
			signal B_i_shifted 		: std_logic_vector((DWIDTH*2)-1 downto 0);
			signal B_i_Accumulated 	: std_logic_vector((DWIDTH*2)-1 downto 0);

			signal A1_0_SubProd 		: std_logic_vector((DWIDTH*2)-1 downto 0);
			signal A3_2_SubProd 		: std_logic_vector((DWIDTH*2)-1 downto 0);
			signal A5_4_SubProd 		: std_logic_vector((DWIDTH*2)-1 downto 0);
			signal A7_6_SubProd 		: std_logic_vector((DWIDTH*2)-1 downto 0);
			signal A3_0_SubProd		: std_logic_vector((DWIDTH*2)-1 downto 0);
			signal A7_4_SubProd		: std_logic_vector((DWIDTH*2)-1 downto 0);
			signal prod 				: std_logic_vector((DWIDTH*2)-1 downto 0); -- Product
begin  
-- =======================================
-- Should be changed to cheaper logic
  process (a_i, b_i)
    variable v_product : unsigned(DWIDTH*2-1 downto 0);    
  begin
    v_product := conv_unsigned(unsigned(a_i) * unsigned(b_i), DWIDTH*2);
    prod <= std_logic_vector(v_product);
  end process;
  
  clock: process (clk)
  begin
  	if (clk'event and clk = '1') then
	  	prod_o <= std_logic_vector(prod);
  	end if;
  end process;
 -- ========================================
 
 
 --*** IMPLEMENTATION OF Computed Partial Product Multipliers ***--
 --*** source: http://www.fpga-guru.com/multipli.htm ************--
 
 -- Prepare shifted b_i first, (b_i<<1)
--	B_i_16Bits  <= "00000000" & b_i;
--	B_i_shifted <= "0000000" & b_i & "0";
--	Cal_Bi_Plus_Bi_Shifted :		csadder  
--						port map 
--						(
--							A => B_i_16Bits, 
--							B => B_i_shifted, 
--							S => B_i_Accumulated, 
--							cin => '0', 
--							carry4 => open, 
--							carry7 => open, 
--							carry8 => open,
--							carry15 => open,
--							carry16 => open
--						);
-- 
-- -- A[1,0]
--	A1_0_SubProd <=	(others => '0') 								when a_i(1 Downto 0)="00" else
--							"00000000" & B_i_16Bits(7 Downto 0)		when a_i(1 Downto 0)="01" else
--							"0000000" & B_i_shifted(8 Downto 0) 	when a_i(1 Downto 0)="10" else
--							"000000" & B_i_Accumulated(9 Downto 0)	when a_i(1 Downto 0)="11" else
--							(others => '0');
-- -- A[3,2]
--	A3_2_SubProd <=	(others => '0') 										when a_i(3 Downto 2)="00" else
--							"000000" & B_i_16Bits(7 Downto 0) & "00"		when a_i(3 Downto 2)="01" else
--							"00000" & B_i_shifted(8 Downto 0) & "00"		when a_i(3 Downto 2)="10" else
--							"0000" & B_i_Accumulated(9 Downto 0) & "00"	when a_i(3 Downto 2)="11" else
--							(others => '0');
-- -- A[5,4]
--	A5_4_SubProd <=	(others => '0') 										when a_i(5 Downto 4)="00" else
--							"0000" & B_i_16Bits(7 Downto 0) & "0000"		when a_i(5 Downto 4)="01" else
--							"000" & B_i_shifted(8 Downto 0) & "0000"		when a_i(5 Downto 4)="10" else
--							"00" & B_i_Accumulated(9 Downto 0) & "0000"	when a_i(5 Downto 4)="11" else
--							(others => '0');
-- -- A[7,6]
--	A7_6_SubProd <=	(others => '0') 										when a_i(7 Downto 6)="00" else
--							"00" & B_i_16Bits(7 Downto 0) & "000000"		when a_i(7 Downto 6)="01" else
--							"0" & B_i_shifted(8 Downto 0) & "000000"		when a_i(7 Downto 6)="10" else
--							B_i_Accumulated(9 Downto 0) & "000000"			when a_i(7 Downto 6)="11" else
--							(others => '0');
-- 
-- -- Calculate First level SubProd(A(7-4) & A(3-0))
-- -- find A3_0_SubProd
-- Cal_A3_0_SubProd :		csadder  
--						port map 
--						(
--							A => A1_0_SubProd, 
--							B => A3_2_SubProd, 
--							S => A3_0_SubProd, 
--							cin => '0', 
--							carry4 => open, 
--							carry7 => open, 
--							carry8 => open,
--							carry15 => open,
--							carry16 => open
--						);
---- find A7_4_SubProd
-- Cal_A7_4_SubProd :		csadder  
--						port map 
--						(
--							A => A5_4_SubProd, 
--							B => A7_6_SubProd, 
--							S => A7_4_SubProd, 
--							cin => '0', 
--							carry4 => open, 
--							carry7 => open, 
--							carry8 => open,
--							carry15 => open,
--							carry16 => open
--						);
--
---- Finally! Find the product of a_i and b_i
--Cal_Final_Product :		csadder  
--						port map 
--						(
--							A => A3_0_SubProd, 
--							B => A7_4_SubProd, 
--							S => prod_o, 
--							cin => '0', 
--							carry4 => open, 
--							carry7 => open, 
--							carry8 => open,
--							carry15 => open,
--							carry16 => open
--						);
 
 --**************************************************************--
 
end rtl;

